﻿package net.wangit.support;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.wangit.MapList;
import net.wangit.Row;
import net.wangit.Unit;
import net.wangit.constants.DatasetKeywords;
import net.wangit.context.ActionContext;
import net.wangit.context.ActionContextHelper;
import net.wangit.context.LocalContext;
import net.wangit.framework.util.UnitDataUtil;
import net.wangit.jdbc.DB;
import net.wangit.jdbc.DBFactory;
import net.wangit.jdbc.table.Column;
import net.wangit.jdbc.table.TableMeta;
import net.wangit.jdbc.table.TableMetaFactory;
import net.wangit.util.Checker;
import net.wangit.util.StringUtil;
import net.wangit.view.element.ElementComponent;
import net.wangit.view.element.component.SelectElement;
import net.wangit.view.element.component.TextFieldElement;
import net.wangit.view.enumeration.EnumerationFactory;
import net.wangit.view.enumeration.EnumerationUtil;
import net.wangit.view.unit.UnitComponent;
import net.wangit.view.unit.UnitFactory;


/**
 * 三维统计
 * 
 * @author watson Feb 25, 2010
 */
public class ListStatUI implements UnitInterceptor {

	private static final String A = "a";
	private static final String B = "b";
	private static final String C = "c";
	private static final String LIST_UNIT_ID = "listunitid";
	private static final String CUSTOM = "onchange=doSubmit()";
	private static Map<String, MapList> mappings;

	private static void addElement(UnitComponent uc, String id, String name) {
		ElementComponent ec = new TextFieldElement();
		ec.setId(id);
		ec.setName(name);
		ec.setShowMode(1);
		ec.setTdWidth(1);
		ec.setTdWidthMode(0);
		uc.addElement(ec);
	}

	private static void addToolbarElement(UnitComponent uc, List<Column> columns,
			String name, String columnNames[], String prefix, boolean notNull) {
		if (columnNames != null) {
			ElementComponent ec = new SelectElement(name, getEnumeration(
					columns, columnNames, notNull));
			ec.setShowMode(3);
			ec.setPrefix(prefix);
			ec.setIsToolbarElement(true);
			ec.setCustom(ListStatUI.CUSTOM);
			uc.addElement(ec);
		}
	}

	private static void clearZero(MapList maplist) {
	}

	private static String[] doMapping(ActionContext ac, String domain,
			String columnNames) {
		String[] names = StringUtil.split(columnNames, ";");
		String[] result = new String[names.length];
		for (int i = 0; i < names.length; i++) {
			String name = names[i];
			int index = name.indexOf(",");
			if (index > 0) {
				String a = name.substring(0, index);
				String b = name.substring(index + 1);
				mappings.put(a, EnumerationFactory
						.getEnumeration(ac, domain, b));
				result[i] = name.substring(0, index);
			} else {
				result[i] = name;
			}
		}

		return result;
	}

	private static String formatValue(double value) {
		if (value == 0.0D)
			return "";
		String result = Double.toString(value);
		int index = result.indexOf(".");
		if (index >= 0
				&& value == Double.parseDouble(result.substring(0, index)))
			return result.substring(0, index);
		else
			return result;
	}

	// 响应的统计图提供MapList数据对象。
	public static MapList getChartData(String domain, String unitId) {
		ActionContext ac = LocalContext.getLocalContext().getActionContext();
		UnitComponent uc = UnitFactory.getUnit(ac, domain, unitId, null);
		MapList statData = null;
		try {
			statData = getStatData(ac, uc);
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (Checker.isEmpty(statData))
			return null;
		int size = statData.size() - 1;
		int width = statData.width() - 1;
		if (width == 1)
			width = 2;
		MapList result = new MapList();
		int rowIndex = 0;
		for (int i = 1; i < width; i++) {
			String key = Integer.toString(i);
			String b = uc.getElement(key).getName();
			for (int j = 0; j < size; j++) {
				Row row = statData.getRow(j);
				String a = row.get("0");
				double y = row.getDouble(key, 0.0D);
				result.put(rowIndex, DatasetKeywords.ROW_KEY, a);
				result.put(rowIndex, ListStatUI.C, b);
				result.put(rowIndex, DatasetKeywords.Y, y);
				rowIndex++;
			}

		}

		return result;
	}

	private static String getColumnLabel(List<Column> columns, String columnName) {
		for (int i = 0; i < columns.size(); i++) {
			Column column = columns.get(i);
			if (columnName.equals(column.getName()))
				return column.getLabel();
		}

		return columnName;
	}

	private static MapList getData1(UnitComponent uc, List<Column> columns,
			MapList listData, String a, String c) {
		addElement(uc, "0", getColumnLabel(columns, a));
		addElement(uc, "1", "".equals(c) ? "" : getColumnLabel(columns, c));
		MapList data = new MapList();
		for (int i = 0; i < listData.size(); i++) {
			Row row = listData.getRow(i);
			String aValue = getText(a, row.get(a));
			double cValue = "".equals(c) ? 1.0D : row.getDouble(c, 0.0D);
			int index = data.findRowIndex("0", aValue);
			if (index < 0) {
				index = data.size();
				data.put(index, "0", aValue);
			}
			double value = cValue + data.getRow(index).getDouble("1", 0.0D);
			data.put(index, "1", formatValue(value));
		}

		total1(data);
		return data;
	}

	private static MapList getData2(UnitComponent uc, MapList listData,
			String a, String b, String c) {
		addElement(uc, "0", "");
		Map<String, String> columnKeys = new HashMap<String, String>();
		MapList data = new MapList();
		for (int i = 0; i < listData.size(); i++) {
			Row row = listData.getRow(i);
			String aValue = getText(a, row.get(a));
			String bValue = getText(b, row.get(b));
			double cValue = "".equals(c) ? 1.0D : row.getDouble(c, 0.0D);
			int index = data.findRowIndex("0", aValue);
			if (index < 0) {
				index = data.size();
				data.put(index, "0", aValue);
			}
			String columnKey = columnKeys.get(bValue);
			if (columnKey == null) {
				columnKey = Integer.toString(columnKeys.size() + 1);
				addElement(uc, columnKey, bValue);
				columnKeys.put(bValue, columnKey);
			}
			double value = cValue
					+ data.getRow(index).getDouble(columnKey, 0.0D);
			data.put(index, columnKey, formatValue(value));
		}

		clearZero(data);
		total2(data, uc);
		return data;
	}

	private static MapList getEnumeration(List<Column> columns, String columnNames[],
			boolean notNull) {
		MapList list = new MapList();
		int index = 0;
		if (!notNull) {
			list.put(index, "name", "");
			list.put(index, "value", "");
			index++;
		}
		for (int i = 0; i < columnNames.length; i++) {
			list.put(index, "value", columnNames[i]);
			list.put(index, "name", getName(columns, columnNames[i]));
			index++;
		}

		return list;
	}

	private static String getName(List<Column> columns, String columnName) {
		for (int i = 0; i < columns.size(); i++) {
			Column column = columns.get(i);
			if (column.getName().equals(columnName))
				return column.getLabel();
		}

		return columnName;
	}

	private static MapList getStatData(ActionContext ac, UnitComponent uc)
			throws Exception {
		mappings = new HashMap<String, MapList>();
		String domain = uc.getDomain();
		String listUnitId = uc.getElementComponent(ListStatUI.LIST_UNIT_ID)
				.getCustom();
		UnitComponent lu = UnitFactory.getUnitWithoutClone(domain, listUnitId);
		TableMeta table = TableMetaFactory.getTableMeta(domain, lu
				.getTableName());
		List<Column> columns = table.getColumns();
		resetElements(ac, uc, columns);
		String a = getValue(ac, uc, ListStatUI.A);
		String b = getValue(ac, uc, ListStatUI.B);
		String c = getValue(ac, uc, ListStatUI.C);
		DB db = DBFactory.getDB(lu.getDatasource());
		String sql = UnitDataUtil.getSql(ac, lu, db);
		MapList listData = db.query(sql);
		MapList result = null;
		if (!Checker.isEmpty(listData))
			if (a.equals(b))
				result = getData1(uc, columns, listData, a, c);
			else
				result = getData2(uc, listData, a, b, c);
		return result;
	}

	private static String getText(String columnName, String columnValue) {
		MapList enumeration = mappings.get(columnName);
		if (Checker.isEmpty(enumeration))
			return columnValue;
		else
			return EnumerationUtil.getEnumerationName(enumeration, columnValue);
	}

	private static String getValue(ActionContext ac, UnitComponent uc,
			String name) {
		ElementComponent ec = uc.getElementComponent(name);
		if (ec == null)
			return "";
		String requestName = (new StringBuilder(String.valueOf(uc.getId())))
				.append(".").append(name).toString();
		String sessionName = (new StringBuilder(String.valueOf(uc.getDomain())))
				.append(".").append(uc.getId()).append(".").append(name)
				.toString();
		String defaultValue = ec.getDefaultValue();
		if (Checker.isEmpty(defaultValue))
			defaultValue = ((MapList) ec.getObject()).getRow(0).get("value");
		String value = ActionContextHelper.getRequest2Session(ac, requestName,
				sessionName, defaultValue);
		ec.setDefaultValue(value);
		return value;
	}

	private static void resetElements(ActionContext ac, UnitComponent uc,
			List<Column> columns) {
		ElementComponent a = uc.getElementComponent(ListStatUI.A);
		String[] aColumns = doMapping(ac, uc.getDomain(), a.getCustom());
		String aPrefix = a.getPrefix();
		ElementComponent b = uc.getElementComponent(ListStatUI.B);
		String[] bColumns = b != null ? doMapping(ac, uc.getDomain(), b
				.getCustom()) : null;
		String bPrefix = b != null ? b.getPrefix() : null;
		ElementComponent c = uc.getElementComponent(ListStatUI.C);
		String[] cColumns = c != null ? doMapping(ac, uc.getDomain(), c
				.getCustom()) : null;
		String cPrefix = c != null ? c.getPrefix() : null;
		uc.removeElement(ListStatUI.A);
		uc.removeElement(ListStatUI.B);
		uc.removeElement(ListStatUI.C);
		uc.removeElement(ListStatUI.LIST_UNIT_ID);
		addToolbarElement(uc, columns, ListStatUI.A, aColumns, aPrefix, true);
		addToolbarElement(uc, columns, ListStatUI.B, bColumns, bPrefix, true);
		addToolbarElement(uc, columns, ListStatUI.C, cColumns, cPrefix, false);
	}

	private static void total1(MapList data) {
		double total = 0.0D;
		int size = data.size();
		for (int i = 0; i < size; i++)
			total += data.getRow(i).getDouble(1, 0.0D);

		data.put(size, "0", "合计");
		data.put(size, "1", formatValue(total));
	}

	private static void total2(MapList data, UnitComponent uc) {
		int size = data.size();
		int width = data.width();
		addElement(uc, Integer.toString(width), "合计");
		double[] totals = new double[width];
		for (int i = 0; i < width; i++)
			totals[i] = 0.0D;

		for (int i = 0; i < size; i++) {
			Row row = data.getRow(i);
			double total = 0.0D;
			int j;
			for (j = 1; j < width; j++) {
				double value = row.getDouble(Integer.toString(j), 0.0D);
				total += value;
				totals[j - 1] += value;
			}

			totals[j - 1] += total;
			data.put(i, Integer.toString(width), formatValue(total));
		}

		data.put(size, "0", "合计");
		for (int i = 0; i < width; i++)
			data.put(size, Integer.toString(i + 1), formatValue(totals[i]));

	}

	public ListStatUI() {
	}

	// 可用来动态设置Unit对象或所属Element对象的属性，需要通过Unit.write(ac)方法返回单元解析结果。
	public String intercept(ActionContext ac, Unit unit) throws Exception {
		unit.setData(getStatData(ac, (UnitComponent) unit));
		return unit.write(ac);
	}
}
